package org.example.config;

import jakarta.annotation.Resource;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.DefaultConnectionKeepAliveStrategy;
import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.http.config.Registry;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.util.TimeValue;
import org.example.config.properties.RestTemplateConfigProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Description: httpclient5 远程调用 配置类
 * Created by 陈宇 on 2024-12-27 15:17
 * Created with IntelliJ IDEA.
 * @author 陈宇
 */
@Configuration
public class RestTemplateConfig {

    @Resource
    private RestTemplateConfigProperties restTemplateConfigProperties;

    @Bean(name = "httpRest")
    public RestTemplate restTemplates() {
        return new RestTemplate(getHttpRequestFactory());
    }

    @Bean
    public ClientHttpRequestFactory getHttpRequestFactory() {
        return new HttpComponentsClientHttpRequestFactory(getHttpClient());
    }

    @Bean
    public CloseableHttpClient getHttpClient() {
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();

        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        connectionManager.setMaxTotal(Integer.parseInt(restTemplateConfigProperties.getMaxTotal()));
        connectionManager.setDefaultMaxPerRoute(Integer.parseInt(restTemplateConfigProperties.getDefaultMaxPerRoute()));
        connectionManager.setValidateAfterInactivity(TimeValue.of(Integer.parseInt(restTemplateConfigProperties.getValidateAfterInactivity()), TimeUnit.MILLISECONDS));

        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(Integer.parseInt(restTemplateConfigProperties.getConnectTimeout()), TimeUnit.MILLISECONDS)
                .setResponseTimeout(Integer.parseInt(restTemplateConfigProperties.getResponseTimeout()), TimeUnit.MILLISECONDS)
                .setConnectionRequestTimeout(Integer.parseInt(restTemplateConfigProperties.getConnectRequestTimeout()), TimeUnit.MILLISECONDS)
                .build();

        List<BasicHeader> headers = new ArrayList<>();
        headers.add(new BasicHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"));
        headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0"));
        headers.add(new BasicHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"));
        headers.add(new BasicHeader("Connection", "keep-alive"));

        CloseableHttpClient build = HttpClientBuilder.create()
                .setDefaultRequestConfig(config)
                .setConnectionManager(connectionManager)
                .setDefaultHeaders(headers)
                .setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy())
                .setRetryStrategy(new DefaultHttpRequestRetryStrategy(3, TimeValue.of(1L, TimeUnit.SECONDS)))
                .build();
        return build;
    }
}
